#pragma once
#include <iostream>
#include <Sock.h>
#include <Channel.h>
#include <buffer.h>
#include <Any.hpp>
#include <functional>
#include <memory>


namespace muduo{
    class Connection;
    typedef enum{CONNECTING,CONNECTED,DISCONNECTING,DISCONNECTED}Connstatu;
    // 使用智能指针来管理Connection，防止在各种事件处理时连接已经关闭
    using PtrConnection = std::shared_ptr<Connection>;
    class Socket;
    class EventLoop; 
    class Connection:public std::enable_shared_from_this<Connection>{
    private:
        uint64_t _con_id;                   //connection的唯一标识id
        int _sock;                          //通信套接字
        EventLoop* _loop;                   //与connection关联的EventLoop
        Socket _socket;                     //套接字操作管理
        Channel _channel;                   //连接的事件管理
        Buffer _inbuffer;                   //输入缓冲区，保存sock中读到的数据
        Buffer _outbuffer;                  //输出缓冲区，保存要发送的数据
        bool _enable_inactive_release;      //设置开启非活跃连接销毁
        Connstatu _statu;                   //当前连接的状态标识
        any _context;                       //请求的接收处理上下文

        // 组件的使用者来决定这四个函数怎么设置
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&,Buffer*)>;
        using CloseCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        ConnectedCallback _connected_callback;  //连接建立后的回调函数
        MessageCallback _message_callback;      //处理收到的信息的回调函数
        CloseCallback _close_callback;          //关闭连接回调函数
        AnyEventCallback _anyevent_callback;    //任意事件回调函数
        // 组件内的连接连接关闭回调，由组件自己设置，因为服务器组件内会把所有连接管理起来，一旦某个连接关闭
        // 就需要从管理处移除掉自己的信息
        CloseCallback _server_close_callback;
    private:
        // channel的五个处理各种事件的回调函数

        void HandleRead();                  //channel管理的fd触发可读事件之后的回调函数
        void HandleWrite();                 //channel管理的fd触发可写事件之后的回调函数
        void HandleClose();                 //channel管理的fd触发关闭事件之后的回调函数
        void HandleError();                 //channel管理的fd触发错误事件之后的回调函数
        void HandleEvent();                 //channel管理的fd触发任意事件之后的回调函数
        /*为了防止线程不安全，把所有对连接的操作放到一个线程之内进行*/
        void EstablishInLoop();             //建立连接之后需要进行各种处理（监控事件，各种回调）
        void ReleaseInLoop();               //真正释放连接的操作
        void SendInLoop(Buffer& buf);       //发送接口，并不直接发送数据，而是将数据放入到发送缓冲区
        void ShutdownInLoop();              //关闭连接的操作，并不直接释放连接，还需要做准备工作
        void EnableInactiveReleaseInLoop(int sec); //设置超时连接关闭
        void CancelInactiveReleaseInLoop(); //取消超时连接关闭
        void UpgradeInLoop(const any& context,const ConnectedCallback& conc,const MessageCallback& mesc,const CloseCallback& closc,const AnyEventCallback& anyc);               //设置上下文以及设置成员函数中的回调函数
    public:
        bool Exist_message_callback();
        Connection(EventLoop* loop,uint64_t conid,int sock);
        int Fd();                           //获取通信的文件描述符
        uint64_t Id();                      //获取连接ID
        bool Connected();                   //连接是否处于CONNECTED状态
        void SetContext(const any& context);                  //设置上下文
        any* GetContext();                  //获取上下文
        void SetConnectedCallback(const ConnectedCallback& conc); 
        void SetMessageCallback(const MessageCallback& mesc);          
        void SetCloseCallback(const CloseCallback& closc);            
        void SetAnyEventCallback(const AnyEventCallback& anyc);
        void SetSvrCloseCallback(const CloseCallback& closc);
        void Establish();
        void Release();
        void Send(const char* data,size_t len);
        void Shutdown();
        void EnableInactiveRelease(int sec);
        void CancelInactive();
        void Upgrade(const any& context,const ConnectedCallback& conc,const MessageCallback& mesc,const CloseCallback& closc,const AnyEventCallback& anyc);
        ~Connection();
    };

}